package com.summli.basic.class08;

/**
 * 给定一棵二叉树的头节点head，
 * * 返回这颗二叉树中最大的二叉搜索子树的大小
 * 二叉搜索树：没有重复值，左子树上所有结点的值均小于它的根结点的值； 若它的右子树不空，则右子树上所有结点的值均大于它的根结点的值
 *
 */

import java.util.ArrayList;

/**
 * 使用递归套路解答本题
 * 结果值包含当前node么？
 * 1.包含成立的条件：left.isBST && right.isBST && left.max<cur.value<right.min -> size = left.size+right.size+1
 * 2.不包含：max(left.size,right.size)
 * 推理返回的递归结果的Info
 * isBST
 * subSize
 * min
 * max
 */
public class Code04_MaxSubBSTSize_2 {

    public static class Info{
        public boolean isBST;
        public int subSize;
        public int min;
        public int max;

        public Info(boolean isBST, int subSize, int min, int max) {
            this.isBST = isBST;
            this.subSize = subSize;
            this.min = min;
            this.max = max;
        }
    }
    public static int maxSubBSTSize2(Code04_MaxSubBSTSize.Node head) {
        if(head == null){
            return 0;
        }
        return process(head).subSize;
    }

    private static Info process(Code04_MaxSubBSTSize.Node cur) {
        if(cur == null){
            return null;
        }
        Info leftInfo = process(cur.left);
        Info rightInfo = process(cur.right);

        int min = cur.value;
        int max = cur.value;
        if(leftInfo != null){
            min = Math.min(min, leftInfo.min);
            max = Math.max(max, leftInfo.max);
        }
        if(rightInfo != null){
            min = Math.min(min, rightInfo.min);
            max = Math.max(max, rightInfo.max);
        }
        // 先定义：不包含cur的情况
        boolean isBST = false;
        int subSize = Math.max((leftInfo== null ? 0:leftInfo.subSize),(rightInfo== null ? 0:rightInfo.subSize));
        if((leftInfo == null?true:(leftInfo.isBST && leftInfo.max < cur.value))&&
                (rightInfo == null?true:rightInfo.isBST  && rightInfo.min > cur.value)){
            isBST = true;
            subSize = (leftInfo == null?0:leftInfo.subSize) + (rightInfo == null?0:rightInfo.subSize)+1;
        }
        return new Info(isBST,subSize,min,max);
    }


    public static void main(String[] args) {
        int maxLevel = 4;
        int maxValue = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
            Code04_MaxSubBSTSize.Node head = Code04_MaxSubBSTSize.generateRandomBST(maxLevel, maxValue);
            if (Code04_MaxSubBSTSize.maxSubBSTSize1(head) != maxSubBSTSize2(head)) {
                System.out.println("Oops!");
                break;
            }
        }
        System.out.println("finish!");
    }

}
